package com.xinyu.service.impl;

import com.xinyu.service.IVProfileService;
import com.xinyu.vo.VProfileVO;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class VProfileServiceImpl implements IVProfileService {

    private final Map<String, List<VProfileVO>> dataCache = new ConcurrentHashMap<>();

    public Map<String, Object> processExcelFile(MultipartFile file) throws IOException {
        List<VProfileVO> rawData = readExcelData(file);
        List<VProfileVO> processedData = processData(rawData);

        String fileId = UUID.randomUUID().toString();
        dataCache.put(fileId, processedData);


        Map<String, Object> result = new HashMap<>();
        result.put("fileId", fileId);
        result.put("data", processedData);
        return result;
    }

    private List<VProfileVO> readExcelData(MultipartFile file) throws IOException {
        List<VProfileVO> data = new ArrayList<>();

        try (Workbook workbook = new XSSFWorkbook(file.getInputStream())) {
            Sheet sheet = workbook.getSheet("1D Profile");
            if (sheet == null) {
                throw new IOException("Sheet '1D Profile' not found");
            }

            // 读取A3-A228和B3-B228的数据
            for (int i = 2; i <= 227; i++) {  // Excel行号从1开始，3-228对应索引2-227
                Row row = sheet.getRow(i);
                if (row != null) {
                    double mm = row.getCell(0).getNumericCellValue();  // A列
                    double mA = row.getCell(1).getNumericCellValue();  // B列
                    data.add(new VProfileVO(mm, mA));
                }
            }
        }

        return data;
    }

    /**
     * 通过滑动窗口计算每个数据点前后 10 个点的平均值，得到平滑后的数据。这样可以有效减少数据中的噪声，保留整体趋势。
     * 接着，我们计算所有平滑值的全局平均值，并将每个平滑值除以这个平均值，得到归一化后的数据。
     * 归一化后的数据围绕 1 上下波动。
     * 平滑处理：减少噪声，保留趋势。
     * 归一化处理：统一数据尺度，便于分析。
     * @param rawData
     * @return
     */
    private List<VProfileVO> processData(List<VProfileVO> rawData) {
        List<VProfileVO> processedData = new ArrayList<>();
        int dataSize = rawData.size();
        double totalAvg = 0;

        // 计算平滑处理后的数据
        for (int i = 0; i < dataSize; i++) {
            int leftPoint = Math.max(0, i - 10);
            int rightPoint = Math.min(dataSize - 1, i + 10);
            double sumValue = 0;
            int pointCount = 0;

            // 计算前后10个点的平均值
            for (int j = leftPoint; j <= rightPoint; j++) {
                double mA = rawData.get(j).getMa();
                if (!Double.isNaN(mA)) {
                    sumValue += mA;
                    pointCount++;
                }
            }

            double avgValue = sumValue / pointCount;
            processedData.add(new VProfileVO(
                    rawData.get(i).getMm(),
                    avgValue
            ));
            totalAvg += avgValue;
        }

        // 归一化处理
        double finalAvg = totalAvg / dataSize;
        for (VProfileVO data : processedData) {
            data.setMa(Double.parseDouble(
                    String.format("%.3f", data.getMa() / finalAvg)
            ));
        }

        return processedData;
    }

    public List<VProfileVO> getProcessedData(String fileId) {
        return dataCache.get(fileId);
    }
}
